package com.atguigu.yygh.cmn.service.impl;

import com.alibaba.excel.EasyExcel;
import com.atguigu.yygh.cmn.listener.DictListener;
import com.atguigu.yygh.cmn.mapper.DictMapper;
import com.atguigu.yygh.cmn.service.DictService;
import com.atguigu.yygh.common.exception.YyghException;
import com.atguigu.yygh.common.result.ResultCode;
import com.atguigu.yygh.model.cmn.Dict;
import com.atguigu.yygh.vo.cmn.DictEeVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 组织架构表 服务实现类
 * </p>
 *
 * @author NanFeng
 * @since 2022-02-16
 */
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 根据数据id查询子数据列表
     * 通过注解实现  缓存 的存入
     *
     * @param id
     * @return
     */
    @Override
    @Cacheable(value = "dict", key = "#id", unless = "#result == null")
    public List<Dict> findChildData(Long id) {

        //根据parent_id查找子记录
        QueryWrapper<Dict> wrapper = new QueryWrapper<>();
        wrapper.eq("parent_id", id);
        List<Dict> dictList = baseMapper.selectList(wrapper);

        //向list集合每个dict对象中设置hasChildren
        for (Dict dict : dictList) {
            Long dictId = dict.getId();
            boolean isChild = this.isChildren(dictId);
            dict.setHasChildren(isChild);
        }

        //避免将 [] 存入redis，判断如果列表大小为0，则返回null
        return dictList.size() == 0 ? null : dictList;
    }

    /**
     * 根据数据id查询子数据列表
     * 向 数据字典添加redis缓存
     *
     * @param
     * @return
     */
/*
    @Override
    public List<Dict> findChildData(Long id) {
        List<Dict> dictList = null;
        try {
            //查询缓存中是否存在数据
            dictList = (List<Dict>) redisTemplate.opsForValue().get("dictList:" + id);
            //如果存在,则从redis缓存中获取数据
            if (dictList != null) {
                return dictList;
            }
        } catch (Exception e) {
            log.error("redis服务器异常：get dictList");
        }

        //如果不存在,则从数据库中获取数据
        //根据parent_id查找子记录
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id", id);

        dictList = baseMapper.selectList(queryWrapper);

        //向list集合每个dict对象中设置hasChildren
        for (Dict dict : dictList) {
            Long dictId = dict.getId();
            Boolean children = this.isChildren(dictId);
            dict.setHasChildren(children);
        }

        try {
            //将数据存入时时redis  并设置超时时间
            redisTemplate.opsForValue().set("dictList:" + id, dictList, 5, TimeUnit.MINUTES);
        } catch (Exception e) {
            log.error("redis服务器异常：get dictList");
        }
        return dictList;

    }
*/

    //导出查询数据
    @Override
    public List<DictEeVo> findExportData() {
        //查询数据库获取所有的 dict 并封装到 dictEeVo中
        List<Dict> dictList = baseMapper.selectList(null);
        ArrayList<DictEeVo> dictEeVos = new ArrayList<>();
        for (Dict dict : dictList) {
            DictEeVo dictEeVo = new DictEeVo();
            //工具类方法,将 dict 数据复制到 dictEeVo 内
            BeanUtils.copyProperties(dict, dictEeVo);
            dictEeVos.add(dictEeVo);
        }
        return dictEeVos;
    }

    //导入数据
    @Override
    public void importDictData(MultipartFile file) {
        try {
            long a = System.currentTimeMillis();
            //MultipartFile 内有流可以调用  baseMapper 不注入的话,在DictListener 中调用,会报 空指针异常
            EasyExcel.read(file.getInputStream(), DictEeVo.class, new DictListener(baseMapper)).sheet().doRead();
            long b = System.currentTimeMillis();
        } catch (IOException e) {
            throw new YyghException(ResultCode.ERROR, "数据字典导入异常", e);
        }
    }

    /**
     * 注意: 要将需要存入缓存的数据作为方法的返回值返回
     * value : 存到缓存中的key
     * key : 一个动态的值 例 :# user.id
     *
     * @param dict
     * @return
     */
    @CachePut(value = "dictTest", key = "#dict.id")
    @Override
    public Dict saveDictWithCacheManager(Dict dict) {
        baseMapper.insert(dict);
        return dict;
    }

    @CacheEvict(value = "dictTest", key = "#id")
    @Override
    public void deleteDictWithCacheManager(Long id) {
        baseMapper.deleteById(id);
    }

    //unless：避免存入null值
    @Override
    @Cacheable(value = {"dictTest"}, key = "#id", unless = "#result == null")
    public Dict getDictWithCacheManager(Long id) {
        return baseMapper.selectById(id);
    }

    /**
     * 根据上级编码与当前值获取数据字典名称
     *
     * @param parentDictCode
     * @param value
     */
    @Override
    public String getNameByParentDictCodeAndValue(String parentDictCode, String value) {
        //根据parentDictCode和value查找dict name
        if (!StringUtils.isEmpty(parentDictCode)) {
            //根据parentDictCode查找父记录
            QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("dict_code", parentDictCode);
            Dict parentDict = baseMapper.selectOne(queryWrapper);
            if (parentDict == null) return "";

            //根据父记录id查找子记录
            QueryWrapper<Dict> queryWrapper2 = new QueryWrapper<>();
            queryWrapper2.eq("parent_id", parentDict.getId()).eq("value", value);
            Dict dict = baseMapper.selectOne(queryWrapper2);
            if (dict == null) return "";

            return dict.getName();
        }

        //针对区 数据的获取,根据value 查询
        QueryWrapper<Dict> queryWrapper3 = new QueryWrapper<>();
        queryWrapper3.eq("value", value);
        Dict dict = baseMapper.selectOne(queryWrapper3);
        return dict.getName();
    }

    /**
     * 根据父节点的dict_code查找子节点列表
     *
     * @param parentDictCode
     * @return
     */
    @Override
    public List<Dict> findByParentDictCode(String parentDictCode) {
        //根据parentDictCode查询到父记录
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("dict_code", parentDictCode);
        Dict parentDict = baseMapper.selectOne(queryWrapper);

        if(parentDict == null) {
            throw new YyghException(ResultCode.ERROR,"数据不存在");
        }

        //根据父记录的ID查询对应的子节点列表
        queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentDict.getId());
        List<Dict> dictList = baseMapper.selectList(queryWrapper);

        return dictList;
    }

    /**
     * 判断id下面是否有子节点
     *
     * @param id
     * @return
     */
    private Boolean isChildren(Long id) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("parent_id", id);
        Integer count = baseMapper.selectCount(queryWrapper);

        return count > 0;
    }
}
